package org.gdstash.ui;

import org.gdstash.item.GDItem;
import org.gdstash.item.GDStash;
import org.gdstash.ui.table.GDMassImportSorter;
import org.gdstash.ui.table.GDMassImportTableModel;
import org.gdstash.ui.util.AdjustablePanel;
import org.gdstash.util.GDImagePool;
import org.gdstash.util.GDMsgFormatter;

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.Collections;
import java.util.List;

public class GDItemImportTablePane extends AdjustablePanel {
    private List<GDItem> data;
    private GDMassImportTableModel model;
    private JTable table;
    private JButton btnSelAll;
    private JButton btnSelValid;
    private JButton btnSelNone;
    private JButton btnClear;

    public GDItemImportTablePane(final List<GDItem> list) {
        this.data = list;
        this.init();
    }

    public GDItemImportTablePane(final GDStash stash) {
        this.data = stash.getItems();
        this.init();
    }

    @Override
    public void adjustUI() {
        Font fntLabel = UIManager.getDefaults().getFont("Label.font");
        Font fntButton = UIManager.getDefaults().getFont("Button.font");
        if (fntButton == null) {
            fntButton = fntLabel;
        }
        Font fntTable = UIManager.getDefaults().getFont("TableHeader.font");
        if (fntTable == null) {
            fntTable = fntLabel;
        }
        fntLabel = fntLabel.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        fntButton = fntButton.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        fntTable = fntTable.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        if (this.btnSelAll == null) {
            (this.btnSelAll = new JButton()).addActionListener(new SelectAllListener());
        }
        this.btnSelAll.setText(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_SEL_ALL"));
        this.btnSelAll.setIcon(GDImagePool.iconMassAll24);
        this.btnSelAll.setFont(fntButton);
        if (this.btnSelValid == null) {
            (this.btnSelValid = new JButton()).addActionListener(new SelectValidListener());
        }
        this.btnSelValid.setText(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_SEL_VALID"));
        this.btnSelValid.setIcon(GDImagePool.iconMassValid24);
        this.btnSelValid.setFont(fntButton);
        if (this.btnSelNone == null) {
            (this.btnSelNone = new JButton()).addActionListener(new SelectNoneListener());
        }
        this.btnSelNone.setText(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_UNSEL_ALL"));
        this.btnSelNone.setIcon(GDImagePool.iconMassNone24);
        this.btnSelNone.setFont(fntButton);
        if (this.btnClear == null) {
            (this.btnClear = new JButton()).addActionListener(new ClearListener());
        }
        this.btnClear.setText(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "BTN_CLEAR"));
        this.btnClear.setIcon(GDImagePool.iconBtnTrash24);
        this.btnClear.setFont(fntButton);
        if (this.table == null) {
            this.table = new JTable();
            final GDMassImportSorter sorter = new GDMassImportSorter();
            this.table.setRowSorter((RowSorter<? extends TableModel>) sorter);
            this.table.getTableHeader().addMouseListener(new SortListener());
            this.setItems(null);
        }
        this.table.getTableHeader().setFont(fntTable);
        this.table.setFont(fntLabel);
        int height = -1;
        if (this.data != null) {
            for (final GDItem item : this.data) {
                final BufferedImage img = item.getImage();
                if (img != null && img.getHeight() > height) {
                    height = img.getHeight();
                }
            }
        }
        if (height == -1) {
            height = 12;
        }
        if (height != -1) {
            height = height * GDStashFrame.iniConfig.sectUI.graphicScale / 100;
            this.table.setRowHeight(height);
        }
        final GDMassImportTableModel model = (GDMassImportTableModel) this.table.getModel();
        model.adjustUI();
        this.updateTableColumns();
    }

    private void init() {
        this.adjustUI();
        GroupLayout layout = null;
        GroupLayout.SequentialGroup hGroup = null;
        GroupLayout.SequentialGroup vGroup = null;
        final JPanel panel = this.buildButtonPanel();
        this.setItems(this.data);
        final JScrollPane scroll = new JScrollPane(this.table);
        scroll.getVerticalScrollBar().setUnitIncrement(2 * GDStashFrame.iniConfig.sectUI.fontSize);
        layout = new GroupLayout(this);
        this.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        hGroup = layout.createSequentialGroup();
        hGroup.addGroup(layout.createParallelGroup().addComponent(scroll).addComponent(panel));
        layout.setHorizontalGroup(hGroup);
        vGroup = layout.createSequentialGroup();
        vGroup.addGroup(layout.createParallelGroup().addComponent(scroll)).addGroup(layout.createParallelGroup().addComponent(panel));
        layout.setVerticalGroup(vGroup);
    }

    private JPanel buildButtonPanel() {
        GroupLayout layout = null;
        GroupLayout.SequentialGroup hGroup = null;
        GroupLayout.SequentialGroup vGroup = null;
        final JPanel panel = new JPanel();
        layout = new GroupLayout(panel);
        panel.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        hGroup = layout.createSequentialGroup();
        hGroup.addGroup(layout.createParallelGroup().addComponent(this.btnSelAll)).addGroup(layout.createParallelGroup().addComponent(this.btnSelValid)).addGroup(layout.createParallelGroup().addComponent(this.btnSelNone)).addGroup(layout.createParallelGroup().addComponent(this.btnClear));
        layout.setHorizontalGroup(hGroup);
        vGroup = layout.createSequentialGroup();
        vGroup.addGroup(layout.createParallelGroup().addComponent(this.btnSelAll).addComponent(this.btnSelValid).addComponent(this.btnSelNone).addComponent(this.btnClear));
        layout.setVerticalGroup(vGroup);
        layout.linkSize(0, this.btnSelAll, this.btnSelValid);
        layout.linkSize(0, this.btnSelAll, this.btnSelNone);
        layout.linkSize(0, this.btnSelAll, this.btnClear);
        layout.linkSize(1, this.btnSelAll, this.btnSelValid);
        layout.linkSize(1, this.btnSelAll, this.btnSelNone);
        layout.linkSize(1, this.btnSelAll, this.btnClear);
        return panel;
    }

    private void updateTableColumns() {
        this.table.getColumnModel().getColumn(3).setCellRenderer(new GDItemTableCellRenderer());
        this.table.getColumnModel().getColumn(4).setCellRenderer(new GDItemTableCellRenderer());
        this.table.getColumnModel().getColumn(5).setCellRenderer(new GDItemTableCellRenderer());
        this.table.getColumnModel().getColumn(6).setCellRenderer(new GDItemTableCellRenderer());
        this.table.getColumnModel().getColumn(7).setCellRenderer(new GDItemTableCellRenderer());
        this.table.getColumnModel().getColumn(8).setCellRenderer(new GDItemTableCellRenderer());
        this.table.getColumnModel().getColumn(9).setCellRenderer(new GDItemTableCellRenderer());
        this.table.getColumnModel().getColumn(10).setCellRenderer(new GDItemTableCellRenderer());
        this.table.getColumnModel().getColumn(11).setCellRenderer(new GDItemTableCellRenderer());
        this.table.getColumnModel().getColumn(12).setCellRenderer(new GDItemTableCellRenderer());
        int scale = 100;
        int size = 12;
        if (GDStashFrame.iniConfig != null) {
            scale = GDStashFrame.iniConfig.sectUI.graphicScale;
            size = GDStashFrame.iniConfig.sectUI.fontSize;
        }
        this.table.getColumnModel().getColumn(0).setPreferredWidth(3 * size);
        this.table.getColumnModel().getColumn(1).setPreferredWidth(3 * size);
        this.table.getColumnModel().getColumn(2).setPreferredWidth(100 * scale / 100);
        this.table.getColumnModel().getColumn(3).setPreferredWidth(25 * size);
        this.table.getColumnModel().getColumn(4).setPreferredWidth(3 * size);
        this.table.getColumnModel().getColumn(5).setPreferredWidth(8 * size);
        this.table.getColumnModel().getColumn(6).setPreferredWidth(8 * size);
        this.table.getColumnModel().getColumn(7).setPreferredWidth(8 * size);
        this.table.getColumnModel().getColumn(8).setPreferredWidth(8 * size);
        this.table.getColumnModel().getColumn(9).setPreferredWidth(8 * size);
        this.table.getColumnModel().getColumn(10).setPreferredWidth(8 * size);
        this.table.getColumnModel().getColumn(11).setPreferredWidth(8 * size);
        this.table.getColumnModel().getColumn(12).setPreferredWidth(25 * size);
        this.table.getColumnModel().getColumn(13).setPreferredWidth(3 * size);
    }

    public void setItems(final List<GDItem> list) {
        this.data = list;
        if (this.data != null) {
            Collections.<GDItem>sort(this.data);
        }
        int height = -1;
        if (this.data != null) {
            for (final GDItem item : this.data) {
                final BufferedImage img = item.getImage();
                if (img != null && img.getHeight() > height) {
                    height = img.getHeight();
                }
            }
        }
        if (height == -1) {
            height = 12;
        }
        this.model = new GDMassImportTableModel(this.data);
        this.table.setModel(this.model);
        this.table.setSelectionModel(new GDItemTableSelectionModel(this.model));
        this.table.setSelectionMode(0);
        final GDMassImportSorter sorter = new GDMassImportSorter(this.model);
        this.table.setRowSorter((RowSorter<? extends TableModel>) sorter);
        if (height != -1) {
            height = height * GDStashFrame.iniConfig.sectUI.graphicScale / 100;
            this.table.setRowHeight(height);
        }
        this.updateTableColumns();
    }

    public List<GDItem> getSelectedItems() {
        return this.model.getSelectedItems();
    }

    private static class GDItemTableCellRenderer extends DefaultTableCellRenderer {
        @Override
        public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int col) {
            if (col < 2) {
                return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
            }
            final JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
            final GDMassImportTableModel model = (GDMassImportTableModel) table.getModel();
            label.setForeground(model.getCellTextColor(row, col));
            return label;
        }
    }

    private static class GDItemTableSelectionModel extends DefaultListSelectionModel {
        private GDMassImportTableModel model;

        public GDItemTableSelectionModel(final GDMassImportTableModel model) {
            this.model = model;
        }

        @Override
        public void setSelectionInterval(final int index0, final int index1) {
            super.setSelectionInterval(index0, index1);
            for (int i = index0; i <= index1; ++i) {
                this.model.rows[i].selected = !this.model.rows[i].selected;
                this.model.fireTableCellUpdated(i, 0);
            }
        }
    }

    private class SortListener extends MouseAdapter {
        @Override
        public void mouseClicked(final MouseEvent ev) {
            final int idx = GDItemImportTablePane.this.table.getColumnModel().getColumnIndexAtX(ev.getX());
            final GDMassImportSorter sorter = (GDMassImportSorter) GDItemImportTablePane.this.table.getRowSorter();
            sorter.sort();
        }
    }

    private class SelectAllListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent e) {
            GDItemImportTablePane.this.model.setSelectAll(true);
        }
    }

    private class SelectValidListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent e) {
            GDItemImportTablePane.this.model.selectValidOnly();
        }
    }

    private class SelectNoneListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent e) {
            GDItemImportTablePane.this.model.setSelectAll(false);
        }
    }

    private class ClearListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent e) {
            GDItemImportTablePane.this.model.setData(null);
        }
    }
}
